Skip to content

fix(spec-specs, tests): EIP-8037 strict block-gas inclusion rule#2892

Open
chfast wants to merge 2 commits into
ethereum:forks/amsterdamfrom
chfast:feat/eip-8037-block-gas-inclusion-strict
Open

fix(spec-specs, tests): EIP-8037 strict block-gas inclusion rule#2892
chfast wants to merge 2 commits into
ethereum:forks/amsterdamfrom
chfast:feat/eip-8037-block-gas-inclusion-strict

Conversation

@chfast

@chfast chfast commented May 21, 2026

Copy link
Copy Markdown
Member

🗒️ Description

EIP-8037 specifies the per-dimension inclusion check at block start as:

min(TX_MAX_GAS_LIMIT, tx.gas) <= regular_gas_available
tx.gas <= state_gas_available

EELS Amsterdam was subtracting intrinsic.state / intrinsic.regular from tx.gas in each dimension, which let a transaction with non-zero state intrinsic (CREATE, EIP-7702 set_code) be included when tx.gas exceeded block.gas_limit by up to intrinsic.regular (state-dim) or intrinsic.state (regular-dim). evmone, revm, and erigon enforce the EIP literally and reject; pre-bump geth rejects too.

Add a parametrized test under EIP-8037 covering the boundary across all post-EIP-7702 tx types and contract-creation kinds, at two block-gas-limit values to avoid hard-coded-cap false-positives.

🔗 Related Issues or PRs

N/A.

✅ Checklist

  • All: Ran fast static checks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:
    just static
  • All: PR title adheres to the repo standard - it will be used as the squash commit message and should start type(scope):.
  • All: Considered updating the online docs in the ./docs/ directory.
  • All: Set appropriate labels for the changes (only maintainers can apply labels).
  • Tests: Ran mkdocs serve locally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.
  • Tests: For PRs implementing a missed test case, update the post-mortem document to add an entry the list.
  • Ported Tests: All converted JSON/YML tests from ethereum/tests or tests/static have been assigned @ported_from marker.

@marioevz

Copy link
Copy Markdown
Member

We are in the process of merging EIP-8037 to forks/amsterdam via this PR: #2901

Once the PR is merged we can point this to the forks/amsterdam branch and then merge.

chfast added a commit to ipsilon/evmone that referenced this pull request Jun 2, 2026
EIP-8037 §"Transaction validation" rule 2 requires a per-tx inclusion
check against the per-dimension remaining budget:

    min(TX_MAX_GAS_LIMIT, tx.gas) <= regular_gas_available
    tx.gas <= state_gas_available

Add `state_block_gas_left` parameter to `validate_transaction` and
enforce both checks for Amsterdam+; default to 0 in the header for
pre-Amsterdam call sites that ignore state-gas. Errors are
`GAS_LIMIT_REACHED` (mapped to `TransactionException.GAS_ALLOWANCE_EXCEEDED`
by EEST).

Also flip the existing Amsterdam intrinsic-cap check from
`GAS_LIMIT_EXCEEDS_MAXIMUM` to `INTRINSIC_GAS_TOO_LOW`: EELS raises
`InsufficientTransactionGasError` here ("the tx can't pay its
intrinsic within the reservoir bound"), not the EIP-7825 absolute-cap
exception.

Note on EELS divergence: amsterdam/fork.py:561-583 currently subtracts
intrinsic.state / intrinsic.regular from tx.gas in each dimension
(`min(TX_MAX_GAS_LIMIT, tx.gas - intrinsic.state)` etc.), which is
more permissive than the EIP. ethereum/execution-specs#2892 aligns
EELS back with the EIP literal. This implementation follows the EIP
text directly — same as revm/erigon/pre-bump-geth.

`test::transition` (the TestState wrapper used by state-transition
unit tests and state tests) passes `block_gas_left` as both budgets,
since those tests run a single tx in a fresh block.

evmone-unittests: 1116 / 1116 pass.
chfast added a commit to ipsilon/evmone that referenced this pull request Jun 8, 2026
EIP-8037 §"Transaction validation" rule 2 requires a per-tx inclusion
check against the per-dimension remaining budget:

    min(TX_MAX_GAS_LIMIT, tx.gas) <= regular_gas_available
    tx.gas <= state_gas_available

Add `state_block_gas_left` parameter to `validate_transaction` and
enforce both checks for Amsterdam+; default to 0 in the header for
pre-Amsterdam call sites that ignore state-gas. Errors are
`GAS_LIMIT_REACHED` (mapped to `TransactionException.GAS_ALLOWANCE_EXCEEDED`
by EEST).

Also flip the existing Amsterdam intrinsic-cap check from
`GAS_LIMIT_EXCEEDS_MAXIMUM` to `INTRINSIC_GAS_TOO_LOW`: EELS raises
`InsufficientTransactionGasError` here ("the tx can't pay its
intrinsic within the reservoir bound"), not the EIP-7825 absolute-cap
exception.

Note on EELS divergence: amsterdam/fork.py:561-583 currently subtracts
intrinsic.state / intrinsic.regular from tx.gas in each dimension
(`min(TX_MAX_GAS_LIMIT, tx.gas - intrinsic.state)` etc.), which is
more permissive than the EIP. ethereum/execution-specs#2892 aligns
EELS back with the EIP literal. This implementation follows the EIP
text directly — same as revm/erigon/pre-bump-geth.

`test::transition` (the TestState wrapper used by state-transition
unit tests and state tests) passes `block_gas_left` as both budgets,
since those tests run a single tx in a fresh block.

evmone-unittests: 1116 / 1116 pass.
EIP-8037 specifies the per-dimension inclusion check at block start as:

    min(TX_MAX_GAS_LIMIT, tx.gas) <= regular_gas_available
    tx.gas <= state_gas_available

EELS Amsterdam was subtracting intrinsic.state / intrinsic.regular from
tx.gas in each dimension, which let a transaction with non-zero state
intrinsic (CREATE, EIP-7702 set_code) be included when tx.gas exceeded
block.gas_limit by up to intrinsic.regular (state-dim) or intrinsic.state
(regular-dim). evmone, revm, and erigon enforce the EIP literally and
reject; pre-bump geth rejects too.

Add a parametrized test under EIP-8037 covering the boundary across all
post-EIP-7702 tx types and contract-creation kinds, at two block-gas-limit
values to avoid hard-coded-cap false-positives.
@chfast chfast force-pushed the feat/eip-8037-block-gas-inclusion-strict branch from 3e7af72 to 8649d8c Compare June 10, 2026 07:55
@chfast chfast changed the base branch from devnets/bal/7 to forks/amsterdam June 10, 2026 07:57

@misilva73 misilva73 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the correct check is the current EIP version and this PR aligns the execution specs with the EIP. So I think we should merge it.

We discussed this some time ago and decided to do this simpler check instead of the one currently in EELS

The strict per-dimension inclusion rule checks
`min(TX_MAX_GAS_LIMIT, tx.gas) <= regular_gas_available` and
`tx.gas <= state_gas_available` (no intrinsic subtraction). Update the
five tests in test_state_gas_reservoir.py that encoded the old
subtracting formula:

- test_block_state_gas_limit_boundary: size tx2 at `state_available`.
- test_creation_tx_regular_check_subtracts_intrinsic_state -> renamed
  test_creation_tx_regular_check_uses_full_tx_gas, now asserts the
  creation tx is rejected (no `intrinsic.state` subtraction).
- test_block_2d_gas_valid_when_cumulative_exceeds_limit: size num_txs
  by the binding state dimension so all txs are includable.
- test_single_tx_state_check_exceeds_block_limit,
  test_creation_tx_state_check_exceeded: drop subtracting-formula
  framing from docstrings, sizing, and assertions.
@codecov

codecov Bot commented Jun 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.53%. Comparing base (84e39e1) to head (7e52026).
⚠️ Report is 1 commits behind head on forks/amsterdam.

Additional details and impacted files
@@                 Coverage Diff                 @@
##           forks/amsterdam    #2892      +/-   ##
===================================================
- Coverage            90.53%   90.53%   -0.01%     
===================================================
  Files                  535      535              
  Lines                32897    32895       -2     
  Branches              3021     3021              
===================================================
- Hits                 29782    29780       -2     
  Misses                2596     2596              
  Partials               519      519              
Flag Coverage Δ
unittests 90.53% <100.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants